use std::{collections::HashMap, fmt::Display, hash::Hash, str::FromStr};

use serde::{Deserialize, Deserializer};

/// serde读取键为实现了`FromStr`的`HashMap`.
///
/// 例如, 可以读取json中键为数字的map.
pub fn deserialize_special_key_map<'de, D, K, V>(deserializer: D) -> Result<HashMap<K, V>, D::Error>
where
    D: Deserializer<'de>,
    K: Deserialize<'de> + Eq + Hash + FromStr,
    <K as FromStr>::Err: Display,
    V: Deserialize<'de>,
{
    let map: HashMap<String, V> = HashMap::deserialize(deserializer)?;
    map.into_iter()
        .map(|(k, v)| k.parse().map(|k| (k, v)))
        .collect::<Result<HashMap<K, V>, _>>()
        .map_err(serde::de::Error::custom)
}

/// 从json文件读取数据.
/// 有问题直接报错
#[allow(unused)]
pub fn read_json_file<T: serde::de::DeserializeOwned>(json_path: &str) -> anyhow::Result<T> {
    let file = std::fs::File::open(json_path)?;
    let reader = std::io::BufReader::new(file);

    serde_json::from_reader(reader).map_err(Into::into)
}

/// 通过生日, 原退休总共要的月数, 和延迟退休的月数来推出 `RetireResult`.
///
/// 支持`delayed_retire_months`为负数表示提前退休.
pub fn calculate_retire_time(
    birth_time: (u32, u32),
    prev_retire_months: u32,
    delayed_retire_months: i32,
) -> super::RetireResult {
    let total_months = (prev_retire_months as i32 + delayed_retire_months) as u32;
    let temp_months = birth_time.1 + total_months;
    let retire_time = (
        birth_time.0 + (temp_months - 1) / 12,
        (temp_months - 1) % 12 + 1,
    );
    let retire_age = total_months as f32 / 12f32;

    super::RetireResult {
        retire_time,
        retire_age,
        delayed_retire_months,
    }
}
